package com.qd.panda.service.refund;

import cn.hutool.core.exceptions.ExceptionUtil;
import com.cdqidi.constant.ConstantDto;
import com.cdqidi.exception.ApiException;
import com.cdqidi.util.SpringContextHolder;
import com.qd.common.panda.constant.PandaConstant;
import com.qd.common.panda.domain.entity.refund.ParkRefundDTO;
import com.qd.common.panda.domain.entity.stroke.UserStrokeOrderDTO;
import com.qd.common.panda.domain.enums.GasStationCompanyNameEnum;
import com.qd.common.sys.domain.entity.log.SendLogDTO;
import com.qd.common.sys.event.SendLogEvent;
import com.qd.common.sys.util.SecurityUtils;
import com.qd.panda.gas.station.req.RefundRequestsReqDTO;
import com.qd.panda.gas.station.shell.last.LastShellHttpServiceImpl;
import com.qd.panda.model.UserStrokeOrder;
import com.qd.panda.model.UserStrokeOrderGas;
import com.qd.panda.model.UserStrokeOrderRefund;
import com.qd.panda.service.stroke.DisplayUtil;
import com.qd.panda.service.stroke.UserStrokeHolderService;
import com.qd.panda.service.stroke.order.UserStrokeOrderGasService;
import com.qd.panda.service.stroke.order.UserStrokeOrderRefundService;
import com.qd.panda.service.stroke.order.UserStrokeOrderService;
import com.qd.system.model.BaseUserInfo;
import com.qd.system.service.user.BaseUserInfoService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpMethod;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;

/**
 * @author sjk
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class RefundService {

    private final ParkRefundService parkRefundService;
    private final UserStrokeOrderService userStrokeOrderService;
    private final UserStrokeOrderGasService userStrokeOrderGasService;
    private final UserStrokeOrderRefundService userStrokeOrderRefundService;
    private final BaseUserInfoService baseUserInfoService;
    private final LastShellHttpServiceImpl lastShellHttpService;
    private final UserStrokeHolderService userStrokeHolderService;


    /**
     * 退款申请
     *
     * @param orderId 订单号
     */
    @Transactional(rollbackFor = Exception.class)
    public void refundRequests(String orderId) {
        UserStrokeOrderDTO userStrokeOrderDTO = userStrokeOrderService.getByIdDto(orderId);
        if (null == userStrokeOrderDTO) {
            return;
        }
        if (!userStrokeOrderDTO.getTripType().equals(DisplayUtil.TRIP_TYPE_2)) {
            throw new ApiException("目前只支持加油退款申请");
        }
        UserStrokeOrderGas strokeOrderGas = userStrokeOrderGasService.getById(orderId);
        if (null == strokeOrderGas) {
            throw new ApiException("加油订单为空,不你退款");
        }
        if (strokeOrderGas.getGasStationCompanyId().equals(GasStationCompanyNameEnum.E_JIA_YOU.getCode())) {
            throw new ApiException("易加油不支持退款申请");
        }
        if (!userStrokeOrderDTO.getPayStatus().equals(DisplayUtil.PAY_STATUS_1)) {
            log.error("只有支付成功的订单才能申请退款,订单: {},支付状态: {}", userStrokeOrderDTO.getOrderId(), userStrokeOrderDTO.getPayStatus());
            return;
        }
        List<UserStrokeOrderRefund> orderRefundList = userStrokeOrderRefundService.getList(userStrokeOrderDTO.getOrderId());
        if (null != orderRefundList && !orderRefundList.isEmpty()) {
            log.error("已经有退款记录,不能重复退款,订单ID: {}", orderId);
            return;
        }

        ParkRefundDTO query = new ParkRefundDTO();
        query.setOrderId(orderId);
        ParkRefundDTO parkRefundDTO = parkRefundService.getOneDto(query);
        query.freeData();
        if (null != parkRefundDTO) {
            log.error("订单号: {} 已处理，此处不在处理", orderId);
            return;
        }
        parkRefundDTO = new ParkRefundDTO();
        parkRefundDTO.setOrderId(userStrokeOrderDTO.getOrderId());
        parkRefundDTO.setOrderAmount(userStrokeOrderDTO.getOrderAmount());
        parkRefundDTO.setPayAmount(userStrokeOrderDTO.getPayAmount());
        parkRefundDTO.setTripType(DisplayUtil.TRIP_TYPE_2);
        parkRefundDTO.setHandlingSituation(-1);
        parkRefundDTO.setAddTime(LocalDateTime.now());
        parkRefundDTO.setUserId(userStrokeOrderDTO.getUserId());
        parkRefundDTO.setMobile(Optional.ofNullable(baseUserInfoService.getById(userStrokeOrderDTO.getUserId())).map(BaseUserInfo::getMobile).orElse(null));
        refundRequestsHttp(orderId,userStrokeOrderDTO.getThirdPartyOrderId());
        parkRefundService.save(parkRefundDTO);

        parkRefundDTO.freeData();
        userStrokeOrderDTO.freeData();
    }

    /**
     * 收到退款申请同意请求
     *
     * @param orderSn       小铁订单号
     * @param orderVenderSn 熊猫订单号
     */
    @Transactional(rollbackFor = Exception.class)
    public void refundGas(String orderSn, String orderVenderSn) {
        UserStrokeOrder userStrokeOrder = userStrokeOrderService.getById(orderVenderSn);
        if (null == userStrokeOrder) {
            return;
        }
        if (!userStrokeOrder.getThirdPartyOrderId().equals(orderSn)) {
            log.error("订单号不匹配,orderId: {},数据库第三方订单号: {},传入的第三方订单号: {}", orderVenderSn, userStrokeOrder.getThirdPartyOrderId(), orderSn);
            return;
        }
        ParkRefundDTO query = new ParkRefundDTO();
        query.setOrderId(orderVenderSn);
        ParkRefundDTO parkRefundDTO = parkRefundService.getOneDto(query);
        query.freeData();
        if (null == parkRefundDTO) {
            return;
        }
        if (parkRefundDTO.getHandlingSituation() == -1) {
            parkRefundDTO.setHandlingSituation(0);
            parkRefundDTO.setReceiveTime(LocalDateTime.now());
            parkRefundService.update(parkRefundDTO);
            parkRefundDTO.freeData();
        }
    }


    private void refundRequestsHttp(String orderId,String thirdPartyOrderId) {
        long start = System.currentTimeMillis();
        SendLogDTO sendLog = new SendLogDTO();
        sendLog.setBid(orderId)
                .setSendState(ConstantDto.SF1)
                .setAddTime(LocalDateTime.now())
                .setLogType(PandaConstant.LOG_TYPE_GAS_REFUND_REQUESTS)
                .setReqMethod(HttpMethod.GET.name());
        try {
            try {
                RefundRequestsReqDTO req = new RefundRequestsReqDTO();
                req.setOrderId(orderId);
                req.setThirdPartyOrderId(thirdPartyOrderId);
                req.setSendLog(sendLog);
                lastShellHttpService.refundRequests(req);
                req.freeData();
            } catch (Exception e) {
                final String message = ExceptionUtil.getMessage(e);
                log.info("加油退款申请失败,orderId： {},error: {}", orderId, message);
                sendLog.setErrMsg(message);
                sendLog.setSendState(ConstantDto.SF0);
                throw new ApiException(e);
            }
        } finally {
            long end = System.currentTimeMillis();
            sendLog.setTimeConsumer(end - start);
            SpringContextHolder.publishEvent(new SendLogEvent(sendLog));
        }
    }

    @Transactional(rollbackFor = Exception.class)
    public void refundComplete(String refundOrderId, String refundAmountStr, int status) {
        LocalDateTime now = LocalDateTime.now();
        ParkRefundDTO parkRefund = Optional.ofNullable(parkRefundService.getByIdDto(refundOrderId)).orElseThrow(() -> new ApiException("退款单号值错误"));
        UserStrokeOrder userStrokeOrder = Optional.ofNullable(userStrokeOrderService.getById(parkRefund.getOrderId())).orElseThrow(() -> new ApiException("订单ID值错误"));
        BigDecimal refundAmount = null;
        if (status == 1) {
            //同意
            if (StringUtils.hasLength(refundAmountStr)) {
                refundAmount = new BigDecimal(refundAmountStr);
            } else {
                //退款金额不传默认使用实际支付金额
                refundAmount = parkRefund.getPayAmount();
            }
            if (refundAmount.compareTo(parkRefund.getPayAmount()) > 0) {
                log.error("退款金额不能大于实际支付金额,退款单ID: {},实际支付金额: {},申请退款金额: {}", refundOrderId, parkRefund.getPayAmount(), refundAmount);
                throw new ApiException("退款金额不能大于实际支付金额");
            }
            userStrokeHolderService.refund(refundAmount,now,userStrokeOrder,"加油退款");
        } else if (status == 2) {
            //拒绝
            log.info("退款被拒绝,退款单ID: {}",refundOrderId);
        } else {
            throw new ApiException("状态值错误");
        }
        if(null !=refundAmountStr){
            parkRefund.setRefundAmount(refundAmount);
        }
        parkRefund.setHandlingSituation(status);
        parkRefund.setHandlingTime(LocalDateTime.now());
        parkRefund.setOrgId(SecurityUtils.getLoginUser().getCurrentOrgId());
        parkRefund.setOperator(SecurityUtils.getLoginUser().getUserId());
        parkRefundService.update(parkRefund);
        parkRefund.freeData();
    }
}
